[IA64] Prepare sioemu for SMP and save & restore.
authorAlex Williamson <alex.williamson@hp.com>
Mon, 10 Mar 2008 17:08:11 +0000 (11:08 -0600)
committerAlex Williamson <alex.williamson@hp.com>
Mon, 10 Mar 2008 17:08:11 +0000 (11:08 -0600)
Use macros instead of constants.

Signed-off-by: Tristan Gingold <tgingold@free.fr>
xen/arch/ia64/vmx/sioemu.c
xen/arch/ia64/vmx/vmx_fault.c
xen/include/asm-ia64/sioemu.h
xen/include/public/arch-ia64/sioemu.h

index 7a533138afcce01d8c80acc72e790e35f1f06330..fe6b740fd322b15251e2faf32a53e5f2cbac6580 100644 (file)
 #include <public/arch-ia64/sioemu.h>
 #include <asm/dom_fw.h>
 #include <asm/debugger.h>
+#include <asm/sal.h>
+#include <asm/vlsapic.h>
 
-static REGS *
-sioemu_deliver (void)
+static void
+sioemu_save_regs (VCPU *vcpu)
 {
-    VCPU *vcpu = current;
     REGS *regs = vcpu_regs(vcpu);
-    unsigned long psr = vmx_vcpu_get_psr(vcpu);
-
-    if (vcpu->vcpu_info->evtchn_upcall_mask)
-        panic_domain (NULL, "sioemu_deliver: aleady in stub mode\n");
-
-    /* All cleared, but keep BN.  */
-    vmx_vcpu_set_psr(vcpu, IA64_PSR_MC | (psr & IA64_PSR_BN));
 
-    /* Save registers. */
     vcpu->arch.arch_vmx.stub_saved[0] = regs->r16;
     vcpu->arch.arch_vmx.stub_saved[1] = regs->r17;
     vcpu->arch.arch_vmx.stub_saved[2] = regs->r18;
@@ -56,13 +49,62 @@ sioemu_deliver (void)
     vcpu->arch.arch_vmx.stub_saved[15] = regs->r31;
     vcpu->arch.arch_vmx.stub_nats =
         (regs->eml_unat >> IA64_PT_REGS_R16_SLOT) & 0xffff;
+}
+
+static void
+sioemu_restore_regs (VCPU *vcpu)
+{
+    REGS *regs = vcpu_regs(vcpu);
+
+    /* First restore registers.  */
+    regs->cr_iip = regs->r28;
+    regs->cr_ifs = regs->r30;
+    vmx_vcpu_set_psr (vcpu, regs->r29);
+
+    regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT);
+    regs->eml_unat |= vcpu->arch.arch_vmx.stub_nats << IA64_PT_REGS_R16_SLOT;
+
+    regs->r16 = vcpu->arch.arch_vmx.stub_saved[0];
+    regs->r17 = vcpu->arch.arch_vmx.stub_saved[1];
+    regs->r18 = vcpu->arch.arch_vmx.stub_saved[2];
+    regs->r19 = vcpu->arch.arch_vmx.stub_saved[3];
+    regs->r20 = vcpu->arch.arch_vmx.stub_saved[4];
+    regs->r21 = vcpu->arch.arch_vmx.stub_saved[5];
+    regs->r22 = vcpu->arch.arch_vmx.stub_saved[6];
+    regs->r23 = vcpu->arch.arch_vmx.stub_saved[7];
+    regs->r24 = vcpu->arch.arch_vmx.stub_saved[8];
+    regs->r25 = vcpu->arch.arch_vmx.stub_saved[9];
+    regs->r26 = vcpu->arch.arch_vmx.stub_saved[10];
+    regs->r27 = vcpu->arch.arch_vmx.stub_saved[11];
+    regs->r28 = vcpu->arch.arch_vmx.stub_saved[12];
+    regs->r29 = vcpu->arch.arch_vmx.stub_saved[13];
+    regs->r30 = vcpu->arch.arch_vmx.stub_saved[14];
+    regs->r31 = vcpu->arch.arch_vmx.stub_saved[15];
+
+}
+
+static REGS *
+sioemu_deliver (void)
+{
+    VCPU *vcpu = current;
+    REGS *regs = vcpu_regs(vcpu);
+    unsigned long psr = vmx_vcpu_get_psr(vcpu);
+
+    if (vcpu->vcpu_info->evtchn_upcall_mask)
+        panic_domain (NULL, "sioemu_deliver: aleady in stub mode\n");
+
+    /* All cleared, but keep BN.  */
+    vmx_vcpu_set_psr(vcpu, IA64_PSR_MC | (psr & IA64_PSR_BN));
+
+    /* Save registers. */
+    sioemu_save_regs (vcpu);
 
     /* Context. */
     regs->r28 = regs->cr_iip;
     regs->r29 = psr;
     regs->r30 = regs->cr_ifs;
 
-    regs->cr_ifs = 0;  // pre-cover
+    regs->cr_ifs = 0;  // pre-cover
 
     regs->cr_iip = vcpu->arch.event_callback_ip;
     regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT);
@@ -90,33 +132,15 @@ sioemu_callback_return (void)
     u64 arg3 = regs->r21;
 
     if ((cmd & ~0x1UL) != 0)
-        panic_domain (NULL,
-                      "sioemu_callback_return: bad operation (%lx)\n", cmd);
+        panic_domain (NULL, "sioemu_callback_return: bad operation (%lx)\n",
+                      cmd);
 
     /* First restore registers.  */
     regs->cr_iip = regs->r28;
     regs->cr_ifs = regs->r30;
     vmx_vcpu_set_psr (vcpu, regs->r29);
 
-    regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT);
-    regs->eml_unat |= vcpu->arch.arch_vmx.stub_nats << IA64_PT_REGS_R16_SLOT;
-
-    regs->r16 = vcpu->arch.arch_vmx.stub_saved[0];
-    regs->r17 = vcpu->arch.arch_vmx.stub_saved[1];
-    regs->r18 = vcpu->arch.arch_vmx.stub_saved[2];
-    regs->r19 = vcpu->arch.arch_vmx.stub_saved[3];
-    regs->r20 = vcpu->arch.arch_vmx.stub_saved[4];
-    regs->r21 = vcpu->arch.arch_vmx.stub_saved[5];
-    regs->r22 = vcpu->arch.arch_vmx.stub_saved[6];
-    regs->r23 = vcpu->arch.arch_vmx.stub_saved[7];
-    regs->r24 = vcpu->arch.arch_vmx.stub_saved[8];
-    regs->r25 = vcpu->arch.arch_vmx.stub_saved[9];
-    regs->r26 = vcpu->arch.arch_vmx.stub_saved[10];
-    regs->r27 = vcpu->arch.arch_vmx.stub_saved[11];
-    regs->r28 = vcpu->arch.arch_vmx.stub_saved[12];
-    regs->r29 = vcpu->arch.arch_vmx.stub_saved[13];
-    regs->r30 = vcpu->arch.arch_vmx.stub_saved[14];
-    regs->r31 = vcpu->arch.arch_vmx.stub_saved[15];
+    sioemu_restore_regs (vcpu);
 
     /* Unmask events.  */
     vcpu->vcpu_info->evtchn_upcall_mask = 0;
@@ -133,8 +157,7 @@ sioemu_deliver_event (void)
     REGS *regs;
 
     regs = sioemu_deliver ();
-
-    regs->r16 = 0;
+    regs->r16 = SIOEMU_CB_EVENT;
 }
 
 void
@@ -144,13 +167,32 @@ sioemu_io_emulate (unsigned long padr, unsigned long data,
     REGS *regs;
 
     regs = sioemu_deliver ();
-    regs->r16 = 1;
+    regs->r16 = SIOEMU_CB_IO_EMULATE;
     regs->r19 = padr;
     regs->r20 = data;
     regs->r21 = data1;
     regs->r22 = word;
 }
 
+void
+sioemu_wakeup_vcpu (int vcpu_id)
+{
+    REGS *regs;
+
+    regs = sioemu_deliver();
+    regs->r16 = SIOEMU_CB_WAKEUP_VCPU;
+    regs->r19 = vcpu_id;
+}
+
+void
+sioemu_sal_assist (struct vcpu *v)
+{
+    REGS *regs;
+
+    regs = sioemu_deliver();
+    regs->r16 = SIOEMU_CB_SAL_ASSIST;
+}
+
 static int
 sioemu_add_io_physmap (struct domain *d, unsigned long start,
                       unsigned long size, unsigned long type)
@@ -187,7 +229,7 @@ sioemu_hypercall (struct pt_regs *regs)
     //        regs->r2, regs->r8, regs->r9);
 
     if (current->vcpu_info->evtchn_upcall_mask == 0)
-        panic_domain (NULL, "sioemu_hypercall: not in stub mode\n");
+        panic_domain(NULL, "sioemu_hypercall: not in stub mode\n");
 
     switch (regs->r2 & FW_HYPERCALL_NUM_MASK_LOW)
     {
@@ -197,20 +239,40 @@ sioemu_hypercall (struct pt_regs *regs)
         break;
     case SIOEMU_HYPERCALL_START_FW:
         regs->cr_iip = regs->r8;
-        vmx_vcpu_set_psr (current, regs->r9);
+        vmx_vcpu_set_psr(current, regs->r9);
         current->vcpu_info->evtchn_upcall_mask = 0;
         break;
     case SIOEMU_HYPERCALL_ADD_IO_PHYSMAP:
-        regs->r8 = sioemu_add_io_physmap (current->domain,
-                                          regs->r8, regs->r9, regs->r10);
+        regs->r8 = sioemu_add_io_physmap(current->domain,
+                                         regs->r8, regs->r9, regs->r10);
         break;
     case SIOEMU_HYPERCALL_GET_TIME:
     {
         uint64_t sec, nsec;
-        get_wallclock (&sec, &nsec);
+        get_wallclock(&sec, &nsec);
         regs->r8 = (sec << 30) + nsec;
         break;
     }
+    case SIOEMU_HYPERCALL_GET_REGS:
+        sioemu_restore_regs(current);
+        break;
+    case SIOEMU_HYPERCALL_SET_REGS:
+        sioemu_save_regs(current);
+        break;
+    case SIOEMU_HYPERCALL_FLUSH_CACHE:
+        regs->r8 = ia64_sal_cache_flush(regs->r8);
+        break;
+    case SIOEMU_HYPERCALL_FREQ_BASE:
+        regs->r8 = ia64_sal_freq_base(regs->r8, &regs->r9, &regs->r10);
+        break;
+    case SIOEMU_HYPERCALL_DELIVER_INT:
+        regs->r8 = vlsapic_deliver_int(current->domain,
+                                       regs->r8, regs->r9, regs->r10);
+        break;
+    case SIOEMU_HYPERCALL_CALLBACK_RETURN:
+        regs->r2 = regs->r27;
+        sioemu_callback_return ();
+        break;
     default:
         panic_domain (NULL, "bad sioemu hypercall %lx\n", regs->r2);
         break;
index 0ae63e16f260430dbb814f0b02fbb3d3e5d16b81..f14372c466ff5fb2b0e9868b0a95526b906f00d3 100644 (file)
@@ -208,8 +208,12 @@ vmx_ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long is
             vcpu_increment_iip(v);
             return IA64_NO_FAULT;
         } else if (iim == DOMN_SAL_REQUEST) {
-            sal_emul(v);
-            vcpu_increment_iip(v);
+            if (d->arch.is_sioemu)
+                sioemu_sal_assist(v);
+            else {
+                sal_emul(v);
+                vcpu_increment_iip(v);
+            }
             return IA64_NO_FAULT;
         } else if (d->arch.is_sioemu
                    && iim == SIOEMU_HYPERPRIVOP_CALLBACK_RETURN) {
index fefd13bcf3dbcbfe3971b139c533941668cc7dc2..55988dc1aeb567a9bf40101afafdf91462b43958 100644 (file)
@@ -26,5 +26,6 @@ extern void sioemu_deliver_event (void);
 extern void sioemu_callback_return (void);
 extern void sioemu_io_emulate (unsigned long padr, unsigned long data,
                               unsigned long data1, unsigned long word);
-
+extern void sioemu_wakeup_vcpu (int vcpu_id);
+extern void sioemu_sal_assist (struct vcpu *v);
 #endif /* __ASM_SIOEMU_H_ */
index c34d6ecd5f837886ced4fb30624eb064121170c4..a98af6a487cc16fa16bf6c3e4fdfc36e688e33f2 100644 (file)
@@ -22,6 +22,9 @@
 #ifndef __XEN_PUBLIC_IA64_SIOEMU_H__
 #define __XEN_PUBLIC_IA64_SIOEMU_H__
 
+/* SIOEMU specific hypercalls.
+   The numbers are the minor part of FW_HYPERCALL_SIOEMU.  */
+
 /* Defines the callback entry point.  r8=ip, r9=data.
    Must be called per-vcpu.  */
 #define SIOEMU_HYPERCALL_SET_CALLBACK 0x01
 /* Get wallclock time.  */
 #define SIOEMU_HYPERCALL_GET_TIME 0x04
 
+/* Get/Set shadow registers.  */
+#define SIOEMU_HYPERCALL_GET_REGS 0x05
+#define SIOEMU_HYPERCALL_SET_REGS 0x06
+
+/* Flush cache.  */
+#define SIOEMU_HYPERCALL_FLUSH_CACHE 0x07
+
+/* Get freq base.  */
+#define SIOEMU_HYPERCALL_FREQ_BASE 0x08
+
+/* Return from callback.  */
+#define SIOEMU_HYPERCALL_CALLBACK_RETURN 0x09
+
+/* Deliver an interrupt.  */
+#define SIOEMU_HYPERCALL_DELIVER_INT 0x0a
+
+/* SIOEMU callback reason.  */
+
+/* An event (from event channel) has to be delivered.  */
+#define SIOEMU_CB_EVENT       0x00
+
+/* Emulate an IO access.  */
+#define SIOEMU_CB_IO_EMULATE  0x01
+
+/* An IPI is sent to a dead vcpu.  */
+#define SIOEMU_CB_WAKEUP_VCPU 0x02
+
+/* A SAL hypercall is executed.  */
+#define SIOEMU_CB_SAL_ASSIST  0x03
+
+
+/* SIOEMU firmware mode hypercalls.  */
+
 /* Return from callback.  r16=0.
    Unmask vcpu events.  */
 #define SIOEMU_HYPERPRIVOP_CALLBACK_RETURN 0x01